package cn.zhentao.service;

import cn.zhentao.config.AlipayConfig;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

@Service
public class AlipayService {

    @Autowired
    private AlipayConfig alipayConfig;

    /**
     * 创建支付宝订单
     */
    public String createAlipayOrder(String orderNo, BigDecimal amount, String subject) throws AlipayApiException {
        try {
            // 公共请求参数
            Map<String, String> params = new TreeMap<>();
            params.put("app_id", alipayConfig.getAppId());
            params.put("method", "alipay.trade.page.pay");
            params.put("format", "json");
            params.put("return_url", alipayConfig.getReturnUrl());
            params.put("charset", alipayConfig.getCharset());
            params.put("sign_type", alipayConfig.getSignType());
            params.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            params.put("version", "1.0");
            params.put("notify_url", alipayConfig.getNotifyUrl());

            // 业务参数
            String bizContent = String.format(
                    "{\"out_trade_no\":\"%s\","
                            + "\"total_amount\":\"%.2f\","
                            + "\"subject\":\"%s\","
                            + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}",
                    orderNo, amount.doubleValue(), subject
            );
            params.put("biz_content", bizContent);

            // 生成签名
            String content = getSignContent(params);
            String sign = AlipaySignature.rsaSign(content, alipayConfig.getPrivateKey(), alipayConfig.getCharset(), alipayConfig.getSignType());
            params.put("sign", sign);

            // 构建请求URL
            StringBuilder url = new StringBuilder("https://openapi-sandbox.dl.alipaydev.com/gateway.do?");
            for (Map.Entry<String, String> entry : params.entrySet()) {
                url.append(entry.getKey())
                        .append("=")
                        .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8))
                        .append("&");
            }

            // 移除最后一个&
            String payUrl = url.substring(0, url.length() - 1);
            System.out.println("生成的支付URL：" + payUrl);

            return payUrl;
        } catch (Exception e) {
            System.err.println("创建支付宝订单失败：" + e.getMessage());
            e.printStackTrace();
            throw new AlipayApiException(e);
        }
    }


    /**
     * 创建支付宝订单（支持附带 passback_params），用于在支付回调时还原用户/套餐等信息
     */
    public String createAlipayOrder(String orderNo, BigDecimal amount, String subject, Map<String, Object> passbackParams) throws AlipayApiException {
        try {
            // 公共请求参数
            Map<String, String> params = new TreeMap<>();
            params.put("app_id", alipayConfig.getAppId());
            params.put("method", "alipay.trade.page.pay");
            params.put("format", "json");
            params.put("return_url", alipayConfig.getReturnUrl());
            params.put("charset", alipayConfig.getCharset());
            params.put("sign_type", alipayConfig.getSignType());
            params.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            params.put("version", "1.0");
            params.put("notify_url", alipayConfig.getNotifyUrl());

            // 业务参数，含 passback_params（需先进行 URL 编码，再参与签名并置于 biz_content 内）
            String passbackEncoded = null;
            if (passbackParams != null && !passbackParams.isEmpty()) {
                String json = new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(passbackParams);
                passbackEncoded = URLEncoder.encode(json, StandardCharsets.UTF_8);
            }
            String bizContent;
            if (passbackEncoded != null) {
                bizContent = String.format(
                        "{\"out_trade_no\":\"%s\"," +
                                "\"total_amount\":\"%.2f\"," +
                                "\"subject\":\"%s\"," +
                                "\"passback_params\":\"%s\"," +
                                "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}",
                        orderNo, amount.doubleValue(), subject, passbackEncoded
                );
            } else {
                bizContent = String.format(
                        "{\"out_trade_no\":\"%s\"," +
                                "\"total_amount\":\"%.2f\","
                                + "\"subject\":\"%s\"," +
                                "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}",
                        orderNo, amount.doubleValue(), subject
                );
            }
            params.put("biz_content", bizContent);

            // 生成签名
            String content = getSignContent(params);
            String sign = AlipaySignature.rsaSign(content, alipayConfig.getPrivateKey(), alipayConfig.getCharset(), alipayConfig.getSignType());
            params.put("sign", sign);

            // 构建请求URL
            StringBuilder url = new StringBuilder("https://openapi-sandbox.dl.alipaydev.com/gateway.do?");
            for (Map.Entry<String, String> entry : params.entrySet()) {
                url.append(entry.getKey())
                        .append("=")
                        .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8))
                        .append("&");
            }

            // 移除最后一个&
            String payUrl = url.substring(0, url.length() - 1);
            System.out.println("生成的支付URL（带passback_params）：" + payUrl);

            return payUrl;
        } catch (Exception e) {
            System.err.println("创建支付宝订单失败：" + e.getMessage());
            e.printStackTrace();
            throw new AlipayApiException(e);
        }
    }

    /**
     * 获取签名内容
     */
    private String getSignContent(Map<String, String> params) {
        StringBuilder content = new StringBuilder();
        params.entrySet().stream()
                .filter(entry -> entry.getValue() != null && entry.getValue().length() > 0)
                .sorted(Map.Entry.comparingByKey())
                .forEach(entry -> {
                    content.append(entry.getKey())
                            .append("=")
                            .append(entry.getValue())
                            .append("&");
                });

        return content.substring(0, content.length() - 1);
    }

    /**
     * 查询支付状态
     */
    public boolean queryPayStatus(String orderNo) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(
                "https://openapi-sandbox.dl.alipaydev.com/gateway.do",
                alipayConfig.getAppId(),
                alipayConfig.getPrivateKey(),
                "json",
                alipayConfig.getCharset(),
                alipayConfig.getPublicKey(),
                alipayConfig.getSignType()
        );

        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent(String.format("{\"out_trade_no\":\"%s\"}", orderNo));

        AlipayTradeQueryResponse response = alipayClient.execute(request);

        if (response.isSuccess()) {
            String tradeStatus = response.getTradeStatus();
            return "TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus);
        }
        return false;
    }

    /**
     * 验证支付宝回调签名
     */
    public boolean verifyNotify(Map<String, String> params) throws AlipayApiException {
        String sign = params.get("sign");
        String content = AlipaySignature.getSignCheckContentV1(params);
        return AlipaySignature.rsa256CheckContent(content, sign, alipayConfig.getPublicKey(), alipayConfig.getCharset());
    }
}